/* REPEATER SPOT
 * StartApplication.java
 *
 * Created on Feb 23, 2009 4:06:06 PM;
 */

package edu.ncsu.csc;

import javax.microedition.io.Connector;
import javax.microedition.io.Datagram;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

import com.sun.spot.io.j2me.radiogram.Radiogram;
import com.sun.spot.io.j2me.radiogram.RadiogramConnection;
import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.peripheral.ISwitch;
import com.sun.spot.sensorboard.peripheral.LEDColor;
import com.sun.spot.util.BootloaderListener;
import com.sun.spot.util.Utils;

/**
 * The startApp method of this class is called by the VM to start the
 * application.
 * 
 * The manifest specifies this class as MIDlet-1, which means it will
 * be selected for execution.
 */
public class StartApplication extends MIDlet {

	static int SPOTS = 8;
	int MAX_SAMPLES = 20;
	// to<-from
	//String[][] routing_table;

	String[] listening_list;

	private void build_routing_table()
	{
/*
		SPOTS = 4;
		routing_table = new String[SPOTS][2];

		// two sensor nodes
		routing_table[0][0] = "0014.4F01.0000.0D20";
		routing_table[0][1] = "0014.4F01.0000.557B";
		routing_table[1][0] = "0014.4F01.0000.0D20";
		routing_table[1][1] = "0014.4F01.0000.3B9E";
		routing_table[2][0] = "0014.4F01.0000.0D20";
		routing_table[2][1] = "0014.4F01.0000.06A0";
		routing_table[3][0] = "0014.4F01.0000.0D20";
		routing_table[3][1] = "0014.4F01.0000.0735";
*/
	}

	private void build_listening_list()
	{
		//* THIS COMMENTED CODE WILL BREAK BECAUSE NOW IN is_in_listening_list method checks if entry is null, not go until we're at end of list */

		/*
		String our_address = IEEEAddress.toDottedHex(RadioFactory.getRadioPolicyManager().getIEEEAddress());
		
		int count = 0;

		for(int k = 0; k < routing_table.length; k++)
			if(our_address.equals(routing_table[k][0]))
				count++;

		listening_list = new String[count];
		for(int k = 0; k < routing_table.length; k++)
		{
			if(routing_table[k][0].equals(our_address))
				listening_list[--count] = routing_table[k][1];
		}
		 */
		listening_list = new String[SPOTS];
		for(int k = 0; k < listening_list.length; k++)
			listening_list[k] = null;
		ISwitch[] switches = EDemoBoard.getInstance().getSwitches();
		int time_out = 5000;
		boolean finished = false;
		for(int k =0 ; k < 8 && !finished; k++)
		{
			int time_passed = 0;
			int selected_spot = 0;
			LEDHelper.disableAll();
			LEDHelper.enable(0);
			while (switches[0].isOpen())
			{
				if(switches[1].isClosed())
				{
					LEDHelper.disable(selected_spot);
					selected_spot = (selected_spot + 1)  % SPOTS;
					LEDHelper.setColor(selected_spot, 128,128,128);
					LEDHelper.enable(selected_spot);
					time_passed = 0;
				}
				Utils.sleep(90);
				time_passed += 100;
				if(time_passed >= time_out)
				{
					finished = true;
					break;
				}
				else
				{
					int brightness = (int)(128 - 128 * ((double)time_passed/time_out));
					LEDHelper.setColor(selected_spot, brightness, brightness, brightness);
				}
			}
			if(!finished)
			{
				LEDHelper.setColorAll(128,128,128);
				LEDHelper.flash(300);
				listening_list[k] = MACList.mac_list[selected_spot];
				Utils.sleep(100);
			}
		}
	}

	private boolean is_in_listening_list(String mac)
	{
		if(true)
			return true;
		for(int k = 0; listening_list[k] != null && k < 8; k++)
		{
			if(listening_list[k].equals(mac))
				return true;
		}
		return false;
	}

     protected void startApp() throws MIDletStateChangeException
	{
		new BootloaderListener().start();   // monitor the USB (if connected) and recognize commands from host

		// visual indicator that SPOT has started

		LEDHelper.setColorAll(0,0,100);
		//LEDHelper.flash(2000);
		LEDHelper.strobeRight(500);
		LEDHelper.strobeLeft(500);


		//
		// This section of code figures out which SPOT the receiver connects to
		//

		build_routing_table();
		build_listening_list();

		// Strobe back and forth green to indicate set up is complete
		LEDHelper.setColorAll(LEDColor.GREEN);
		LEDHelper.strobeRight(1000);
		LEDHelper.strobeLeft(1000);

		RadiogramConnection in_conn = null;
		RadiogramConnection out_conn = null;
		while(true)
		{
			try
			{
				LEDHelper.setColorAll(0,255,0);
				LEDHelper.flash(1000);

				in_conn = (RadiogramConnection)Connector.open("radiogram://:101");
				in_conn.setMaxBroadcastHops(1);
				out_conn = (RadiogramConnection)Connector.open("radiogram://broadcast:101");
				out_conn.setMaxBroadcastHops(1);
				Radiogram in_dg = (Radiogram)in_conn.newDatagram(1 + 6 + MAX_SAMPLES * 4);
				Datagram out_dg = out_conn.newDatagram(1 + 6 + MAX_SAMPLES * 4);
	
				for(int i = 0; true; i++)
				{
					in_conn.receive(in_dg);

					if(is_in_listening_list(in_dg.getAddress()))
					{
						byte quality = (byte)(in_dg.getLinkQuality() >> 5);
						LEDHelper.enableRange(0,quality);
						if(quality < 7)
							LEDHelper.disableRange(quality+1,7);
						Utils.sleep(10);
						LEDHelper.disableAll();
						Utils.sleep(10);

						int bytes_received = in_dg.getLength();

						for(int j = 0; j < bytes_received; j++)
						{
							out_dg.writeByte(in_dg.readByte());
						}
						out_conn.send(out_dg);
						out_dg.reset();
					}

					in_dg.reset();
				}
			}
			catch(Exception e)
			{
				System.out.println(e);
				e.printStackTrace();
				try
				{
					in_conn.close();
					out_conn.close();
				}
				catch(Exception ee)
				{

				}

				LEDHelper.setColorAll(255,0,0);
				LEDHelper.blink(200,300,3);
			}
		}
    }

    protected void pauseApp() {
        // This is not currently called by the Squawk VM
    }

    /**
     * Called if the MIDlet is terminated by the system.
     * I.e. if startApp throws any exception other than MIDletStateChangeException,
     * if the isolate running the MIDlet is killed with Isolate.exit(), or
     * if VM.stopVM() is called.
     * 
     * It is not called if MIDlet.notifyDestroyed() was called.
     *
     * @param unconditional If true when this method is called, the MIDlet must
     *    cleanup and release all resources. If false the MIDlet may throw
     *    MIDletStateChangeException  to indicate it does not want to be destroyed
     *    at this time.
     */
    protected void destroyApp(boolean unconditional) throws MIDletStateChangeException {
		LEDHelper.disableAll();
       
    }
}
